package com.xiaoxi.bms.service.user.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoxi.bms.common.constant.enumeration.statuscode.other.CommonEnums;
import com.xiaoxi.bms.common.constant.enumeration.statuscode.system.LoginSystemEnums;
import com.xiaoxi.bms.common.exception.BMSException;
import com.xiaoxi.bms.common.util.AuthUtils;
import com.xiaoxi.bms.domain.user.BMSUser;
import com.xiaoxi.bms.domain.user.BMSUserDetail;
import com.xiaoxi.bms.domain.user.dto.BMSUserDetailDTO;
import com.xiaoxi.bms.domain.user.vo.BMSUserDetailVO;
import com.xiaoxi.bms.domain.user.vo.BMSUserPasswordChangeVO;
import com.xiaoxi.bms.mapper.user.BMSUserDetailMapper;
import com.xiaoxi.bms.service.common.circulation.ExportDataToExcelService;
import com.xiaoxi.bms.service.user.BMSUserDetailService;
import com.xiaoxi.bms.service.user.BMSUserRoleService;
import com.xiaoxi.bms.service.user.BMSUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author xiaoxi
 * @version 1.0
 * @date 2022/6/22 23:11
 */
@Service("bmsUserDetailServiceImpl")
@Slf4j
public class BMSUserDetailServiceImpl extends ServiceImpl<BMSUserDetailMapper, BMSUserDetail> implements BMSUserDetailService, ExportDataToExcelService {

    @Resource
    private BMSUserDetailMapper bmsUserDetailMapper;

    @Resource
    private BMSUserService bmsUserService;

    @Resource
    private BMSUserRoleService bmsUserRoleService;

    @Override
    public IPage<BMSUserDetailVO> getAllUserInfo(BMSUserDetailDTO bmsUserDetailDTO, Pageable pageable) {

        int curPage = Math.max(1, pageable.getPageNumber());
        int start = (curPage - 1) * pageable.getPageSize();

        List<BMSUserDetailVO> bmsUserDetailVOList = bmsUserDetailMapper.getUserInfoByPage(bmsUserDetailDTO, start, pageable.getPageSize());
        Long count = bmsUserDetailMapper.getUserInfoByCount(bmsUserDetailDTO);
        IPage<BMSUserDetailVO> iPage = new Page<>();
        iPage.setRecords(bmsUserDetailVOList);
        iPage.setTotal(count);
        return iPage;
    }

    @Override
    public BMSUserDetailVO getUserInfoByUserDetailId(Long userDetailId) throws BMSException {

        // 用户详情
        BMSUserDetail bmsUserDetail = bmsUserDetailMapper.selectById(userDetailId);
        if (Objects.isNull(bmsUserDetail)) {
            throw new BMSException(LoginSystemEnums.INCORRECT_USER_ID);
        }

        // 角色
        List<Long> userRoleList = bmsUserRoleService.getUserRoleListByUserId(bmsUserDetail.getUserId());

        BMSUserDetailVO bmsUserDetailVO = new BMSUserDetailVO();
        BeanUtils.copyProperties(bmsUserDetail, bmsUserDetailVO);

        bmsUserDetailVO.setRoles(userRoleList);

        BMSUser bmsUser = bmsUserService.selectUserById(bmsUserDetailVO.getUserId());

        bmsUserDetailVO.setUsername(bmsUser.getUsername());
        bmsUserDetailVO.setEnabled(bmsUser.isEnabled());
        bmsUserDetailVO.setAccountNonLocked(bmsUser.isAccountNonLocked());

        BMSUserPasswordChangeVO bmsUserPasswordChangeVO = new BMSUserPasswordChangeVO();
        bmsUserPasswordChangeVO.setUsername(bmsUser.getUsername());
        bmsUserPasswordChangeVO.setVersion(bmsUser.getVersion());
        bmsUserDetailVO.setBmsUserPasswordChangeVO(bmsUserPasswordChangeVO);

        return bmsUserDetailVO;
    }

    @Override
    @Transactional(rollbackFor = BMSException.class)
    public void updateUserInfo(BMSUserDetailVO bmsUserDetailVO) throws BMSException {

        if (Objects.isNull(bmsUserDetailVO.getVersion())) {
            throw new BMSException(CommonEnums.PLEASE_SEND_THE_VERSION);
        }

        // 防止有人 提供 假的 userId
        BMSUserDetail selectById = bmsUserDetailMapper.selectById(bmsUserDetailVO.getId());
        if (Objects.isNull(selectById)) {
            throw new BMSException(LoginSystemEnums.INCORRECT_USER_ID);
        }

        long userId = selectById.getUserId();

        // 1. user -- user_password_change_log
        if (bmsUserDetailVO.getModifyPassword()) {
            bmsUserService.changePassword(bmsUserDetailVO.getBmsUserPasswordChangeVO(), false);
        }

        Boolean enableStatus = bmsUserService.enableUserStatus(userId, bmsUserDetailVO.getEnabled());
        if (!enableStatus) {
            throw new BMSException(CommonEnums.INFORMATION_OUT_OF_DATE);
        }
        Boolean accountNonLockedStatus = bmsUserService.accountNonLockedUserStatus(userId, bmsUserDetailVO.getAccountNonLocked());
        if (!accountNonLockedStatus) {
            throw new BMSException(CommonEnums.INFORMATION_OUT_OF_DATE);
        }

        // 2. user_detail
        BMSUserDetail bmsUserDetail = new BMSUserDetail();
        bmsUserDetail.setId(bmsUserDetailVO.getId());
        bmsUserDetail.setName(bmsUserDetailVO.getName());
        bmsUserDetail.setTelNumber(bmsUserDetailVO.getTelNumber());
        bmsUserDetail.setEmail(bmsUserDetailVO.getEmail());
        bmsUserDetail.setHeadImg(bmsUserDetailVO.getHeadImg());
        bmsUserDetail.setSex(bmsUserDetailVO.getSex());
        bmsUserDetail.setIntroduce(bmsUserDetailVO.getIntroduce());
        bmsUserDetail.setVersion(bmsUserDetailVO.getVersion());
        bmsUserDetail.setRemark(bmsUserDetailVO.getRemark());

        int num = bmsUserDetailMapper.updateById(bmsUserDetail);
        if (num == 0) {
            throw new BMSException(CommonEnums.INFORMATION_OUT_OF_DATE);
        }

        // 3. user_role
        bmsUserRoleService.updateUserRoleList(userId, bmsUserDetailVO.getRoles());

    }

    @Override
    @Transactional(rollbackFor = BMSException.class)
    public void createUserInfo(BMSUserDetailVO bmsUserDetailVO) throws BMSException {

        // 1. user - bms_user_password_change_log
        BMSUser bmsUser = bmsUserService.initPassword(bmsUserDetailVO.getUsername(), bmsUserDetailVO.getEnabled());

        // 2. user_detail
        BMSUserDetail bmsUserDetail = new BMSUserDetail();
        bmsUserDetail.setUserId(bmsUser.getId());
        bmsUserDetail.setName(bmsUserDetailVO.getName());
        bmsUserDetail.setTelNumber(bmsUserDetailVO.getTelNumber());
        bmsUserDetail.setEmail(bmsUserDetailVO.getEmail());
        bmsUserDetail.setHeadImg(bmsUserDetailVO.getHeadImg());
        bmsUserDetail.setSex(bmsUserDetailVO.getSex());
        bmsUserDetail.setIntroduce(bmsUserDetailVO.getIntroduce());
        bmsUserDetail.setRemark(bmsUserDetailVO.getRemark());
        bmsUserDetailMapper.insert(bmsUserDetail);

        // 3. bms_user_role
        bmsUserRoleService.addUserRoleListByUserId(bmsUser.getId(), bmsUserDetailVO.getRoles());

    }

    @Override
    public BMSUserDetailVO getCurrentUserInfo() throws BMSException {

        // 用户详情
        BMSUserDetail bmsUserDetail = getUserInfoByUserId(AuthUtils.getCurrentUser().getId());

        if (Objects.isNull(bmsUserDetail)) {
            throw new BMSException(LoginSystemEnums.INCORRECT_USER_ID);
        }

        // 角色
        List<Long> userRoleList = bmsUserRoleService.getUserRoleListByUserId(bmsUserDetail.getUserId());

        BMSUserDetailVO bmsUserDetailVO = new BMSUserDetailVO();
        BeanUtils.copyProperties(bmsUserDetail, bmsUserDetailVO);

        bmsUserDetailVO.setRoles(userRoleList);

        bmsUserDetailVO.setUsername(AuthUtils.getCurrentUser().getUsername());

        return bmsUserDetailVO;
    }

    @Override
    public BMSUserDetail editCurrentUserInfo(BMSUserDetailVO bmsUserDetailVO) throws BMSException {

        if (Objects.isNull(bmsUserDetailVO.getVersion())) {
            throw new BMSException(CommonEnums.PLEASE_SEND_THE_VERSION);
        }

        BMSUserDetail bmsUserDetail = getUserInfoByUserId(AuthUtils.getCurrentUser().getId());

        if (!bmsUserDetail.getVersion().equals(bmsUserDetailVO.getVersion())) {
            throw new BMSException(CommonEnums.INFORMATION_OUT_OF_DATE);
        }

        bmsUserDetail.setName(bmsUserDetailVO.getName());
        bmsUserDetail.setTelNumber(bmsUserDetailVO.getTelNumber());
        bmsUserDetail.setEmail(bmsUserDetailVO.getEmail());
        bmsUserDetail.setHeadImg(bmsUserDetailVO.getHeadImg());
        bmsUserDetail.setSex(bmsUserDetailVO.getSex());
        bmsUserDetail.setIntroduce(bmsUserDetailVO.getIntroduce());

        bmsUserDetailMapper.updateById(bmsUserDetail);

        return bmsUserDetail;
    }

    @Override
    public BMSUserDetail getUserInfoByUserId(Long userId) {
        QueryWrapper<BMSUserDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        return bmsUserDetailMapper.selectOne(queryWrapper);
    }

    @Override
    public void updateLastLoginTime(Long userId) {
        UpdateWrapper<BMSUserDetail> bmsUserDetailUpdateWrapper = new UpdateWrapper<>();
        bmsUserDetailUpdateWrapper.eq("user_id", userId);
        bmsUserDetailUpdateWrapper.set("last_login_time", LocalDateTime.now());
        bmsUserDetailMapper.update(null, bmsUserDetailUpdateWrapper);
    }

    @Override
    public List<String> tableHeader(String... args) {

        List<String> tableHeader = new ArrayList<>();

        tableHeader.add("序号");
        tableHeader.add("姓名");
        tableHeader.add("手机号");
        tableHeader.add("邮箱");
        tableHeader.add("头像地址");
        tableHeader.add("性别");
        tableHeader.add("个人介绍");
        tableHeader.add("最后登录时间");
        tableHeader.add("版本号");
        tableHeader.add("创建时间");
        tableHeader.add("修改时间");
        tableHeader.add("备注");
        tableHeader.add("启用");
        tableHeader.add("锁定");

        return tableHeader;
    }

    @Override
    public <T> IPage<T> tableContent(T objDTO, Pageable pageable, String... args) {
        return (IPage<T>) getAllUserInfo((BMSUserDetailDTO) objDTO, pageable);
    }
}
